/**
 * TokenProcessor类是一个单例类
 * 
 */
package com.hww.util;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

/**
 * @author 黄文威
 *
 * 2014-4-27 下午8:27:31
 */
public class TokenProcessor {
	
	static final String TOKEN_KEY = "org.hww.token";
	
	private static TokenProcessor instance = new TokenProcessor();
	
	/**
	 * getInstance()方法获得单例类的实例
	 * @return  TokenProcessor
	 */
	public static TokenProcessor getInstance(){
		return instance;
	}
	/**
	 * 最近一次生成令牌的时间戳
	 */
	private long previous;
	
	/**
	 * @param request
	 * @return  boolean
	 */
	public synchronized boolean isTokenValid(HttpServletRequest request){
		//得到请求的Session
		HttpSession session = request.getSession(false);
		if(session == null)
			return false;
		
		//从Session中取出保存的令牌值
		String saved = (String) session.getAttribute(TOKEN_KEY);
		if(saved == null){
			return false;
		}
		
		//清除Session中的令牌值
		resetToken(request);
		
		//得到请求参数中的令牌值
		String token = request.getParameter(TOKEN_KEY);
		if(token ==null)
			return false;
		return saved.equals(token);
	}
	
	/**
	 * @param request  void
	 * 
	 * 清除Session中的令牌值
	 */
	public synchronized void resetToken(HttpServletRequest request){
		
		//这里需要注意的是request.getSession(false)方法，
		//
		HttpSession session = request.getSession(false);
		if(session == null)
			return;
		session.removeAttribute(TOKEN_KEY);
	}
	
	/**
	 * 产生一个令牌，保存到Session中，
	 * 如果当前Session不存在，则创建一个新的Session
	 * @param request  void
	 */
	public synchronized void saveToken(HttpServletRequest request){
		HttpSession session = request.getSession();
		String token = generateToken(request);
		if(token != null)
			session.setAttribute(TOKEN_KEY, token);
	}
	
	/**
	 * 根据用户会话ID与当前的系统时间生成一个唯一的令牌
	 * @param request
	 * @return  String
	 */
	public synchronized String generateToken(HttpServletRequest request){
		HttpSession session = request.getSession();
		try{
			byte id[] = session.getId().getBytes();
			long current = System.currentTimeMillis();
			if(current == previous)
				current ++;
			previous = current;
			
			byte now[] = new Long(current).toString().getBytes();
			MessageDigest md = MessageDigest.getInstance("MD5");
			md.update(id);
			md.update(now);
			return toHex(md.digest());
		}catch(NoSuchAlgorithmException e){
			return null;
		}
	}
	
	/**
	 * 将一个字节数组转换为一个十六进制数字的字符串
	 * 
	 * @param buffer
	 * @return  String
	 */
	private String toHex(byte buffer[]){
		StringBuffer sb = new StringBuffer(buffer.length*2);
		for(int i=0;i<buffer.length;i++){
			sb.append(Character.forDigit(buffer[i]&0xf0 >>4,16));
		}
		return sb.toString();
	}
	
	/**
	 * 从Session中得到令牌值，入股破Session中没有保存的令牌值，则生成一个新的令牌值
	 * @param request
	 * @return  String
	 */
	public synchronized String getToken(HttpServletRequest request){
		HttpSession session = request.getSession(false);
		if(null == session)
			return null;
		String token = (String)session.getAttribute(TOKEN_KEY);
		if(null == token){
			token = generateToken(request);
			if(token != null){
				session.setAttribute(TOKEN_KEY, token);
				return token;
			}else
				return null;
		}
		else
			return token;
	}
}

